package cn.wolfcode.p2p.business.service.impl;

import cn.wolfcode.p2p.base.domain.Account;
import cn.wolfcode.p2p.base.qo.QueryObject;
import cn.wolfcode.p2p.base.service.IAccountService;
import cn.wolfcode.p2p.base.util.Constants;
import cn.wolfcode.p2p.base.util.UserContext;
import cn.wolfcode.p2p.business.domain.*;
import cn.wolfcode.p2p.business.mapper.PaymentScheduleMapper;
import cn.wolfcode.p2p.business.service.*;
import cn.wolfcode.p2p.business.util.CalculatetUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.tomcat.util.bcel.Const;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@Service@Transactional
public class PaymentScheduleServiceImpl implements IPaymentScheduleService {

    @Autowired
    private PaymentScheduleMapper paymentScheduleMapper;
    @Autowired
    private IAccountService accountService;
    @Autowired
    private IPaymentScheduleDetailService paymentScheduleDetailService;
    @Autowired
    private IAccountFlowService accountFlowService;
    @Autowired
    private IBidService bidService;
    @Autowired
    private ISystemAccountService systemAccountService;
    @Autowired
    private ISystemAccountFlowService systemAccountFlowService;
    @Autowired
    private IBidRequestService bidRequestService;
    @Autowired
    private ICreditTransferService creditTransferService;

    @Override
    public int save(PaymentSchedule paymentSchedule) {
        return paymentScheduleMapper.insert(paymentSchedule);
    }

    @Override
    public int update(PaymentSchedule paymentSchedule) {
        return paymentScheduleMapper.updateByPrimaryKey(paymentSchedule);
    }

    @Override
    public PaymentSchedule get(Long id) {
        return paymentScheduleMapper.selectByPrimaryKey(id);
    }

    @Override
    public PageInfo queryPage(QueryObject qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        List result = paymentScheduleMapper.queryData(qo);
        return new PageInfo(result);
    }

    @Override
    public void returnMoney(Long id) {
        //1.根据传过来的id获取还款对象
        PaymentSchedule ps = this.get(id);
        //判断还款对象是否为空,状态是否是还款中

        if (ps != null && ps.getState() == Constants.PAYMENT_STATE_NORMAL) {
            //判断当前登录的用户是否是还款人
            //2.判断账户的钱是否足够
            Account account = accountService.getCurrent();
            if (ps.getBorrowUser().getId().equals(UserContext.getCurrent().getId())
                    &&account.getUsableAmount().compareTo(ps.getTotalAmount())>=0
                    ){
                //3.如果还款,还款对象状态设置为已还,设置还款时间payDate
                ps.setState(Constants.PAYMENT_STATE_DONE);
                ps.setPayDate(new Date());
                 this.update(ps);
                //还款明细对象设置还款状态
                paymentScheduleDetailService.updatePayState(ps.getId(), ps.getPayDate());

                //4.还款人的账户
                //可用金额减少,待还本息减少,剩余授信额度增加,生成还款成功的流水
                account.setUsableAmount(account.getUsableAmount().subtract(ps.getTotalAmount()));
                account.setUnReturnAmount(account.getUnReturnAmount().subtract(ps.getTotalAmount()));
                account.setRemainBorrowLimit(account.getRemainBorrowLimit().add(ps.getPrincipal()));
                accountService.update(account);
                accountFlowService.createReturnMoneyFlow(account, ps.getTotalAmount());

                //5.投资人的账户
                //可用金额增加,待收本金和待收利息减少,生成回款成功的流水
                Account bidUserAccount;
                Long bidUserId;
                Map<Long, Account> accountMap = new HashMap<Long, Account>();
                SystemAccount systemAccount = systemAccountService.get();
                List<CreditTransfer> needCancels = new ArrayList<CreditTransfer>();
                for (PaymentScheduleDetail psd : ps.getDetails()) {
                    bidUserId = psd.getInvestorId();
                    bidUserAccount = accountMap.get(bidUserId);
                    if (bidUserAccount == null){
                        bidUserAccount = accountService.get(bidUserId);
                        accountMap.put(bidUserId, bidUserAccount);
                    }
                    bidUserAccount.setUsableAmount(bidUserAccount.getUsableAmount().add(psd.getTotalAmount()));
                    bidUserAccount.setUnReceivePrincipal(bidUserAccount.getUnReceivePrincipal().subtract(psd.getPrincipal()));
                    bidUserAccount.setUnReceiveInterest(bidUserAccount.getUnReceiveInterest().subtract(psd.getInterest()));
                    accountFlowService.createReceiveReturnMoney(bidUserAccount,psd.getTotalAmount());
                    //支付平台利息管理费(10%),可用金额减少,生成支付利息管理费的流水
                    BigDecimal interestManagerCharge = CalculatetUtil.calInterestManagerCharge(psd.getInterest());
                    bidUserAccount.setUsableAmount(bidUserAccount.getUsableAmount().subtract(interestManagerCharge));
                    accountFlowService.createPayInterestManagerChargeFlow(bidUserAccount, interestManagerCharge);
                    //6.系统账户可用金额增加,生成收取利息管理费的流水
                    systemAccount.setUsableAmount(systemAccount.getUsableAmount().add(interestManagerCharge));
                    systemAccountFlowService.createReceiveInterestManagerChargeFlow(systemAccount,interestManagerCharge);

                    //处理债权转让问题
                    //如果还款明细处于转让中,找到对应的债权标
                    if (psd.getIntrans() == Constants.IN_TRANS) {
                        CreditTransfer cancel = creditTransferService.findNeedCancel(psd.getBidId());
                        needCancels.add(cancel);
                    }
                }

                //统一更新投资人的账户
                for (Account accountTemp : accountMap.values()) {
                    accountService.update(accountTemp);
                }
                systemAccountService.update(systemAccount);

                //撤销债权标
                for (CreditTransfer needCancel : needCancels) {
                    creditTransferService.cancel(needCancel);
                }

                //7.如何判断已经还清了该借款
                //根据还款对象中关联的bidRequestId,查询出改借款下的所有的还款对象
                List<PaymentSchedule> paymentScheduleList = this.queryByBidRequestId(ps.getBidRequestId());
                for (PaymentSchedule paymentSchedule : paymentScheduleList) {
                    //判断还款对象的标的状态是否都是已还清
                    if (paymentSchedule.getState() != Constants.PAYMENT_STATE_DONE) {
                        //没有还清
                        return;
                    }
                }
                //如果还清了
                //借款对象和投资对象的标的状态:已还清
                BidRequest bidRequest = bidRequestService.get(ps.getBidRequestId());
                bidRequest.setBidRequestState(Constants.BIDREQUEST_STATE_COMPLETE_PAY_BACK);
                bidRequestService.update(bidRequest);
                bidService.updateState(bidRequest.getId(), Constants.BIDREQUEST_STATE_COMPLETE_PAY_BACK);
            }
        }
    }

    @Override
    public List<PaymentSchedule> queryByBidRequestId(Long bidRequestId) {
        return paymentScheduleMapper.queryByBidRequestId(bidRequestId);
    }

    @Override
    public List<PaymentSchedule> queryYesterdayOverduePaymentScheduleList() {
        Date now = new Date();
        return paymentScheduleMapper.queryYesterdayOverduePaymentScheduleList(now, Constants.PAYMENT_STATE_NORMAL);
    }
}
